package com.zz.hhbl.utils

import org.locationtech.jts.geom.Coordinate
import org.locationtech.jts.geom.GeometryFactory
import org.locationtech.jts.geom.LinearRing
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.sqrt

object GeofenceUtils {
    private const val EARTH_RADIUS = 6371000.0 // 地球半径，单位：米
    /**
     * 计算两个经纬度点之间的距离（单位：米）。
     *
     * @param point1 第一个点。
     * @param point2 第二个点。
     * @return 两点之间的距离。
     */
    fun haversineDistance(point1: Coordinate, point2: Coordinate): Double {
        val dLat = Math.toRadians(point2.y - point1.y)
        val dLon = Math.toRadians(point2.x - point1.x)
        val a = sin(dLat / 2) * sin(dLat / 2) + cos(Math.toRadians(point1.y)) * cos(Math.toRadians(point2.y)) * sin(dLon / 2) * sin(dLon / 2)
        val c = 2 * atan2(sqrt(a), sqrt(1 - a))
        return EARTH_RADIUS * c
    }

    /**
     * 检查一个点是否在圆形电子围栏内。
     *
     * @param point     待检测点。lon,lat
     * @param center    圆心点。
     * @param radius    圆的半径，单位：米。
     * @return 如果点在圆内返回true，否则返回false。
     */
    @Deprecated("错误")
    fun isPointInCircle(point: Coordinate, center: Coordinate, radius: Double): Boolean {
        val geometryFactory = GeometryFactory()
        // 创建圆心和缓冲区表示的圆
        val centerPoint = geometryFactory.createPoint(center)
        val circle = centerPoint.buffer(radius)
        // 创建待检测点
        val p = geometryFactory.createPoint(point)
        // 判断点是否在圆内
        return circle.contains(p)
    }


    /**
     * 检查一个点是否在多边形电子围栏内。
     * @param point      待检测点。
     * @param polygon    多边形顶点列表。
     * @return 如果点在多边形内返回true，否则返回false。
     */
    fun isPointInPolygon(point: Coordinate, polygon: List<Coordinate>): Boolean {
        val geometryFactory = GeometryFactory()
        // 创建线性环（必须闭合，首尾点相同）
        val closedPolygon = polygon + polygon.first()
        val ring = geometryFactory.createLinearRing(closedPolygon.toTypedArray())
        val poly = geometryFactory.createPolygon(ring, null)
        // 创建待检测点
        val p = geometryFactory.createPoint(point)
        // 判断点是否在多边形内
        return poly.contains(p)
    }


    /**
     * 检查一个点是否在多边形（支持环形）电子围栏内。
     * @param point      待检测点。
     * @param outerRing  外环顶点列表。
     * @param innerRings 可选的内环顶点列表（表示孔）。
     * @return 如果点在多边形内且不在孔内，返回true，否则返回false。
     */
    fun isPointInPolygonWithHoles(point: Coordinate, outerRing: List<Coordinate>, innerRings: List<List<Coordinate>>?): Boolean {
        val geometryFactory = GeometryFactory()
        // 创建外环
        val closedOuterRing = outerRing + outerRing.first()
        val outer = geometryFactory.createLinearRing(closedOuterRing.toTypedArray())
        // 创建内环（如果有）
        val holes = innerRings?.map { innerRing ->
            val closedInnerRing = innerRing + innerRing.first()
            geometryFactory.createLinearRing(closedInnerRing.toTypedArray())
        }?.toTypedArray()
        // 创建多边形
        val polygon = geometryFactory.createPolygon(outer, holes)
        // 创建点
        val p = geometryFactory.createPoint(point)
        // 判断点是否在多边形内
        return polygon.contains(p)
    }

}
